﻿using Core.Framework;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.Repository;
using System;
using System.Threading.Tasks;

namespace Ocelot.Extension
{
    public static class OcelotConfigurationMiddlewareExtensions
    {
        public static IApplicationBuilder UseModifyConfiguration(this IApplicationBuilder builder, string path = "/modify/configuration")
        {
            return builder.UseMiddleware<OcelotConfigurationMiddleware>(path);
        }

        public class OcelotConfigurationMiddleware
        {
            private readonly RequestDelegate _next;
            private readonly string path;
            private static bool isIni = false;

            public OcelotConfigurationMiddleware(RequestDelegate next, string path)
            {
                this._next = next ?? throw new ArgumentNullException(nameof(next));
                this.path = path;
            }

            public async Task Invoke(HttpContext context)
            {
                if (isIni.Equals(false))
                {
                    if (AppSetting.IsSetiToolGatewaySqlString())
                    {
                        await this.ModifyConfiguration(context.RequestServices);
                        isIni = true;
                    }
                }
                //else if (context.Request.Path.Equals(new PathString(path)))
                //{
                //    // 这里需要身份验证
                //    await this.ModifyConfiguration(context.RequestServices);
                //    context.Response.StatusCode = 200;
                //    return;
                //}

                await this._next(context);
            }

            private async Task ModifyConfiguration(IServiceProvider serviceProvider)
            {
                var configurationRepo = serviceProvider.GetRequiredService<IFileConfigurationRepository>();
                var ocelotConfiguration = await configurationRepo.Get();
                if (!ocelotConfiguration.IsError)
                {
                    var internalConfigurationRepo = serviceProvider.GetRequiredService<IInternalConfigurationRepository>();
                    var internalConfigurationCreator = serviceProvider.GetRequiredService<IInternalConfigurationCreator>();
                    var internalConfiguration = await internalConfigurationCreator.Create(ocelotConfiguration.Data);
                    if (!internalConfiguration.IsError)
                    {
                        internalConfigurationRepo.AddOrReplace(internalConfiguration.Data);
                    }
                    else
                    {
                        throw new Exception($"init api route configuration error, {string.Join(", ", internalConfiguration.Errors)}");
                    }
                }
                else
                {
                    throw new Exception($"update ocelot configuration error, error in get ocelot configuration from configurationRepo, error messages:{string.Join(", ", ocelotConfiguration.Errors)}");
                }
            }
        }
    }
}
